home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 2 / Atari Mega Archive CD - Volume 2.iso / minix / up1510b.tgz / up1510b / src / tools / init.c < prev    next >
C/C++ Source or Header  |  1990-07-15  |  13KB  |  407 lines

  1. /* This process is the father (mother) of all Minix user processes.  When
  2.  * Minix comes up, this is process number 2, and has a pid of 1.  It
  3.  * executes the /etc/rc shell file, and then reads the /etc/ttys file to
  4.  * determine which terminals need a login process.  The ttys file consists
  5.  * of three-field lines as follows:
  6.  *    abc
  7.  * where
  8.  *    a = 0 (line disabled = no shell), 1 (enabled = shell started)
  9.  *        2 (enabled through a GETTY)
  10.  *    b = a-r defines UART paramers (baud, bits, parity), 0 for console
  11.  *    c = line number or line name
  12.  *
  13.  * The letters a-r correspond to the 18 entries of the uart table below.
  14.  * For example, 'a' is 110 baud, 8 bits, no parity; 'b' is 300 baud, 8
  15.  * bits, no parity; 'j' is 2400 baud, 7 bits, even parity; etc.  If the
  16.  * third field is a digit, then the terminal device will be /dev/tty{c},
  17.  * otherwise it will be /dev/{c}.  Note that since login cheats in
  18.  * determining the slot number, entries in /etc/ttys must always be in
  19.  * minor device number order - the first line should be for tty0, the
  20.  * second for tty1, and so on.
  21.  *
  22.  * Example /etc/tty file (the text following # should not be in /etc/ttys)
  23.  *    1c0    # /dev/tty0 is enabled as 1200 baud, no parity
  24.  *    2c1    # /dev/tty1 is enabled using /etc/getty for speed detection
  25.  *    0c2    # /dev/tty2 is disabled
  26.  *    
  27.  * If any of the /etc/tty entries start with a 2, the file /etc/getty must
  28.  * be present and executable.
  29.  *
  30.  * If the files /usr/adm/wtmp and /etc/utmp exist and are writable, init
  31.  * (with help from login) will maintain login accounting.  Sending a
  32.  * signal 1 (SIGHUP) to init will cause it to reread /etc/ttys and start
  33.  * up new shell processes if necessary.  It will not, however, kill off
  34.  * login processes for lines that have been turned off; do this manually.
  35.  */
  36. #include <sys/types.h>
  37. #include <fcntl.h>
  38. #include <limits.h>
  39. #include <signal.h>
  40. #include <sgtty.h>
  41. #include <string.h>
  42. #include <time.h>
  43. #include <unistd.h>
  44. #include <utmp.h>
  45.  
  46. #define CONSNAME    "/dev/tty0"    /* system console device */
  47.  
  48. #define SHELL1        "/bin/sh"
  49. #define SHELL2        "/usr/bin/sh"
  50. #define LOGIN1        "/bin/login"
  51. #define LOGIN2        "/usr/bin/login"
  52. #define GETTY        "/etc/getty"    /* GETTY for dial IN/OUT */
  53.  
  54. #define PIDSLOTS    8        /* maximum number of ttys entries */
  55. #define TTYSBUF        (8 * PIDSLOTS)    /* buffer for reading /etc/ttys */
  56. #define STACKSIZE    (192 * sizeof(char *))    /* init's stack */
  57.  
  58. #define EXIT_TTYFAIL    253        /* child had problems with tty */
  59. #define EXIT_EXECFAIL    254        /* child couldn't exec something */
  60. #define EXIT_OPENFAIL    255        /* child couldn't open something */
  61.  
  62. struct uart {
  63.   int baud;
  64.   int flags;
  65. } uart[] = {
  66.   B110,   BITS8,        /* 'a':  110 baud, 8 bits, no parity */
  67.   B300,   BITS8,        /* 'b':  300 baud, 8 bits, no parity */
  68.   B1200,  BITS8,        /* 'c': 1200 baud, 8 bits, no parity */
  69.   B2400,  BITS8,        /* 'd': 2400 baud, 8 bits, no parity */
  70.   B4800,  BITS8,        /* 'e': 4800 baud, 8 bits, no parity */
  71.   B9600,  BITS8,        /* 'f': 9600 baud, 8 bits, no parity */
  72.  
  73.   B110,   BITS7 | EVENP,    /* 'g':  110 baud, 7 bits, even parity */
  74.   B300,   BITS7 | EVENP,    /* 'h':  300 baud, 7 bits, even parity */
  75.   B1200,  BITS7 | EVENP,    /* 'i': 1200 baud, 7 bits, even parity */
  76.   B2400,  BITS7 | EVENP,    /* 'j': 2400 baud, 7 bits, even parity */
  77.   B4800,  BITS7 | EVENP,    /* 'k': 4800 baud, 7 bits, even parity */
  78.   B9600,  BITS7 | EVENP,    /* 'l': 9600 baud, 7 bits, even parity */
  79.  
  80.   B110,   BITS7 | ODDP,        /* 'm':  110 baud, 7 bits, odd parity */
  81.   B300,   BITS7 | ODDP,        /* 'n':  300 baud, 7 bits, odd parity */
  82.   B1200,  BITS7 | ODDP,        /* 'o': 1200 baud, 7 bits, odd parity */
  83.   B2400,  BITS7 | ODDP,        /* 'p': 2400 baud, 7 bits, odd parity */
  84.   B4800,  BITS7 | ODDP,        /* 'q': 4800 baud, 7 bits, odd parity */
  85.   B9600,  BITS7 | ODDP        /* 'r': 9600 baud, 7 bits, odd parity */
  86. };
  87.  
  88. #define NPARAMSETS (sizeof uart / sizeof(struct uart))
  89.  
  90. struct slotent {
  91.   int onflag;            /* should this ttyslot be on? */
  92.   int pid;            /* pid of login process for this tty line */
  93.   int exit;            /* eit status of child */
  94.   char name[8];            /* name of this tty */
  95.   int flags;            /* sg_flags field for this tty */
  96.   int speed;            /* sg_ispeed for this tty */
  97. };
  98.  
  99. struct slotent slots[PIDSLOTS];    /* init table of ttys and pids */
  100.  
  101. char stack[STACKSIZE];        /* init's stack */
  102. char *stackpt = &stack[STACKSIZE];
  103. char **environ;            /* declaration required by library routines */
  104. extern int errno;
  105.  
  106. char *CONSOLE = CONSNAME;    /* name of system console */
  107. struct sgttyb args;        /* buffer for TIOCGETP */
  108. int gothup = 0;            /* flag, showing signal 1 was recieved */
  109. int pidct = 0;            /* count of running children */
  110.  
  111. char *env[] = { (char *)0 };    /* tiny environment for execle */
  112.  
  113. main()
  114. {
  115.   int pid;            /* pid of child process */
  116.   int fd;            /* fd of console for error messages */
  117.   int i;            /* loop variable */
  118.   int status;            /* return status from child process */
  119.   struct slotent *slotp;    /* slots[] pointer */
  120.   void onhup();            /* SIGHUP interrupt catch routine */
  121.  
  122.   sync();            /* force buffers out onto disk */
  123.  
  124.   /* Execute the /etc/rc file. */
  125.   if(fork()) {
  126.     /* Parent just waits. */
  127.     wait(&status);
  128.   } else {
  129.     /* Child exec's the shell to do the work. */
  130.     if(open("/etc/rc", 0) < 0) exit(EXIT_OPENFAIL);
  131.     dup(open(CONSOLE, 1));    /* std output, error */
  132.     execle(SHELL1, SHELL1, (char *)0, env);
  133.     execle(SHELL2, SHELL2, (char *)0, env);
  134.     exit(EXIT_EXECFAIL);    /* impossible, we hope */
  135.   }
  136.  
  137.   /* Log system reboot. */
  138.   wtmp("reboot", "~~", "~", 0, BOOT_TIME, -1);
  139.  
  140.   /* Read the /etc/ttys file. */
  141.   readttys();
  142.   
  143.   /* Main loop. If login processes have already been started up, wait for one
  144.    * to terminate, or for a HUP signal to arrive. Start up new login processes
  145.    * for all ttys which don't have them. Note that wait() also returns when
  146.    * somebody's orphan dies, in which case ignore it.
  147.    * First set up the signals.
  148.    */
  149.  
  150.   for (i = 1; i <= _NSIG; i++) signal(i, SIG_IGN);
  151.   signal(SIGHUP, onhup);
  152.  
  153.   while(1) {
  154.     sync();
  155.  
  156.     if( pidct && (pid = wait(&status)) > 0 ) {
  157.         /* Search to see which line terminated. */
  158.         for(slotp = slots; slotp < &slots[PIDSLOTS]; ++slotp) {
  159.             if(slotp->pid == pid) {
  160.                 pidct--;
  161.                 slotp->pid = 0;    /* now no login process */
  162.                 slotp->exit = status;
  163.  
  164.                 if(((status >> 8) & 0xFF) == EXIT_TTYFAIL) {
  165.                 fd = open(CONSOLE, 1);
  166.                 write(fd, "init: tty problems, shutting down ", 39);
  167.                 write(fd, slotp->name, sizeof slotp->name);
  168.                 write(fd, "\n", 1);
  169.  
  170.                 close(fd);
  171.                 slotp->onflag = 0;
  172.                 }
  173.                 break;
  174.             }
  175.           }
  176.     }
  177.  
  178.     /* If a signal 1 (SIGHUP) is received, reread /etc/ttys. */
  179.     if(gothup) {
  180.         readttys();
  181.         gothup = 0;
  182.     }
  183.  
  184.     /* See which lines need a login process started up. */
  185.     for(slotp = slots; slotp < &slots[PIDSLOTS]; ++slotp) {
  186.         if(slotp->onflag && slotp->pid <= 0)
  187.             startup(slotp - slots, DEAD_PROCESS, LOGIN_PROCESS);
  188.     }
  189.   }
  190. }
  191.  
  192. void onhup()
  193. {
  194.   gothup = 1;
  195.   signal(SIGHUP, onhup);
  196. }
  197.  
  198. readttys()
  199. {
  200.   /* (Re)read /etc/ttys. */
  201.  
  202.   char ttys[TTYSBUF];            /* buffer for reading /etc/ttys */
  203.   register char *p;            /* current pos. within ttys */
  204.   char *endp;                /* pointer to end of ttys buffer */
  205.   int fd;                /* file descriptor for /etc/ttys */
  206.   struct slotent *slotp = slots;    /* entry in slots[] */
  207.   char *q;                /* pointer for copying ttyname */
  208.  
  209.   if((fd = open("/etc/ttys", 0)) < 0) {
  210.     write(open(CONSOLE, 1), "init: can't open /etc/ttys\n", 27);
  211.     while (1) ;        /* just hang -- system cannot be started */
  212.   }
  213.  
  214.   /* Read /etc/ttys file. */
  215.   endp = (p = ttys) + read(fd, ttys, TTYSBUF);
  216.   *endp = '\n';
  217.  
  218.   /* The first character of each line on /etc/ttys tells what to do:
  219.    *     0 = do not enable line
  220.    *    1 = enable line for regular login
  221.    *    2 = use /etc/getty on this line to detect modem speed dynamically
  222.    */
  223.   while(p < endp) {
  224.     switch(*p++) {
  225.         case '0':        /* no getty/login */
  226.             slotp->onflag = 0;
  227.             break;
  228.  
  229.         case '1':        /* use login on this line */
  230.             slotp->onflag = 1;
  231.             break;
  232.  
  233.         case '2':        /* use GETTY on this line */
  234.             slotp->onflag = 2;
  235.             break;
  236.  
  237.         default:
  238.             /* First char of line is rotten.  Skip this entry. */
  239.             while(*p++ != '\n') ;    /* read until '\n' hit */
  240.             continue;    /* go to next entry */
  241.     }
  242.     slotp->exit = 0;
  243.     slotp->flags = CRMOD | XTABS | ECHO;        /* sg_flags setting */
  244.  
  245.     /* Now examine the second cha